/*
 * GuildServer.cpp
 *
 *  Created on: 2014. 7. 28.
 *      Author: mega
 */

#include "../User.h"
#include "../Proxy.h"
#include "../Static.h"
#include "../protocol/Guild.h"

#include "../NLogic/BackEndServerInfo.h"
#include "../NLogic/Function.h"
#include "../NLogic/Buff.h"
#include "../NLogic/Bag.h"
#include "../NLogic/Item.h"
#include "../NLogic/Space.h"

#include "../NState/Static.h"
#include "../command/world/CS_CHAT_MESSAGE.h"

#include "GuildServer.h"



namespace ProjectZ { namespace NProxy {

GuildServer::GuildServer() : _idx(0), _bConnect(false)
{
	_pSession = new Session;
	_pSession->SetState(new State());
	_pSession->SetOwner(this);
}

GuildServer::~GuildServer()
{
	delete _pSession->GetState();
	delete _pSession;
}

bool
GuildServer::Connect(int idx, std::string ip, int port)
{
	_clsInfo.eType	= ::Network::Session::Info::SERVER;
	_clsInfo.ip		= ip.c_str();
	_clsInfo.port	= port;
	_clsInfo.keepAliveTime = 3000 * 10;
	_idx = idx;

	bool bConnect = _pSession->Connect(_clsInfo);

	if (true == bConnect)
		_bConnect = true;

	return bConnect;
}

void
GuildServer::OnDisconnect()
{
#if 0
	auto tree = GetUserTree();
	auto itr = tree.begin();
	for ( ; itr != tree.end(); ++itr)
	{
		User * pUser = itr->second;
		if (NULL == pUser)
			continue;

		::ProjectZ::Session * pSession = pUser->GetSession();
		if (NULL == pSession)
			continue;

		NLogic::BackEndServerInfo * pBackEndServerInfo = pUser->GetBackEndServerInfo();
		if (NULL == pBackEndServerInfo)
			continue;

		if (pBackEndServerInfo->GetData()._guildServerIndex != this->_idx)
			continue;

		User::State * pState = pUser->GetState();
		if (NULL != pState)
			pState->OnClose(pUser, true);
	}
#endif

	_bConnect = false;
	this->setTime();
}

bool
GuildServer::OnTime(int id, void * param)
{
	_pSession = new Session;
	_pSession->SetState(new State());
	_pSession->SetOwner(this);

	bool bConnect = _pSession->Connect(_clsInfo);

	if (true == bConnect)
		_bConnect = true;
	else
		this->setTime();

	return false;
}

void
GuildServer::setTime()
{
	::Dispatcher::Timer::Argument clsArgument(1000 * 15, 0, NULL, this);
	::Dispatcher::GETTIMER()->SetTimer(clsArgument);
}


void
GuildServer::Msg::OnOpenAck(Dispatcher::Session * pSession, ::Network::Packet * pPacket)
{
	PROCESSLOG("[GUILD] OnOpen Server IP : %s PORT : %d", pSession->GetNetworkPeerInfo().ip.c_str(), pSession->GetNetworkPeerInfo().port);

	Session * pLocalSession = static_cast<Session *>(pSession);
	GuildServer * pGuildServer = static_cast<GuildServer *>(pLocalSession->GetOwner());
	::ProjectZ::Static::Instance()._guildServer[pGuildServer->GetIdx()] = true;
}

void
GuildServer::Msg::OnCloseAck(Dispatcher::Session * pSession, ::Network::Packet * pPacket)
{
	PROCESSLOG("[GUILD] OnClose Server IP : %s PORT : %d", pSession->GetNetworkPeerInfo().ip.c_str(), pSession->GetNetworkPeerInfo().port);

	Session * pLocalSession = static_cast<Session *>(pSession);
	GuildServer * pGuildServer = static_cast<GuildServer *>(pLocalSession->GetOwner());

	pGuildServer->OnDisconnect();
}

void
GuildServer::Msg::OnLeaveGuildAck(Dispatcher::Session * pSession, ::Network::Packet * pPacket)
{
	LeaveGuildAck ack;
	const char * pBuf = pPacket->GetOffsetPtr();
	size_t len = pPacket->m_nEnd - pPacket->m_nOffset;

	if (false == ack.Load(&pBuf, len))
		return;

	User * pUser = NProxy::GetUser(ack.user_seq);
	if (NULL == pUser)
	{
		DEBUGLOG("%s : pUser is NULL", __FUNCTION__);
		return;
	}

	if (ACK_OK == ack.result)
	{
		pUser->SetGuildSeq(0);
		pUser->SetGuildGrade(0);
		pUser->SetGuildName("");
		pUser->FlushUserInfo();

		// 길드 버프 초기화
		NLogic::Buff * pBuff = pUser->GetBuff();
		if (NULL != pBuff)
		{
			NLogic::Buff::Data * pBuffData = pBuff->GetData(NLogic::Buff::BuffType::GUILD);
			if (NULL != pBuffData)
				pBuffData->Clear();
		}
	}

	if (true == pUser->GetDisconnectStatus())
	{
		pUser->OnDisconnect();
		return;
	}

	pUser->SetState(NState::Static::Instance().MAINFRIENDLIST());

	::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();
	*pAck << static_cast<int16_t>(ack.result);
	pAck->MakePacket(CMD_SC_GUILD_LEAVE);
	pUser->Send(pAck);

	// 버프 정보 전송
	NLogic::NFunction::SendSkillBuff(pUser);

	// 내정보 타 유저에게 전송
	NLogic::Space * pSpace = pUser->GetSpace();
	if (NULL == pSpace)
		return;

	const NLogic::Space::USERTREE & clsUserTree = pSpace->GetUserTree();
	std::for_each(clsUserTree.begin(), clsUserTree.end(), [&](const std::pair<const int, ProjectZ::User*>& pair) {
		if (NULL != pair.second && pair.first != pUser->GetUserSeq())
		{
			NLogic::NFunction::SendCharacterInfoSimple(pUser, pair.second);
		}
	} );
}

void
GuildServer::Msg::OnKickoutGuildMemberAck(Dispatcher::Session * pSession, ::Network::Packet * pPacket)
{
	KickoutGuildMemberAck ack;
	const char * pBuf = pPacket->GetOffsetPtr();
	size_t len = pPacket->m_nEnd - pPacket->m_nOffset;

	if (false == ack.Load(&pBuf, len))
		return;

	User * pUser = NProxy::GetUser(ack.user_seq);
	if (NULL == pUser)
	{
		DEBUGLOG("%s : pUser is NULL", __FUNCTION__);
		return;
	}

	if (ACK_OK != ack.result)
	{
		::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();
		*pAck << static_cast<int16_t>(ack.result);
		pAck->MakePacket(CMD_SC_GUILD_EXILE);
		pUser->Send(pAck);
		return;
	}

	::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();
	*pAck << static_cast<int16_t>(ACK_OK);
	*pAck << static_cast<uint32_t>(ack.guild_point);
	pAck->MakePacket(CMD_SC_GUILD_EXILE);
	pUser->Send(pAck);
}

void
GuildServer::Msg::OnGuildBuffGachyaAck(Dispatcher::Session * pSession, ::Network::Packet * pPacket)
{
	GuildBuffGachyaAck ack;
	const char * pBuf = pPacket->GetOffsetPtr();
	size_t len = pPacket->m_nEnd - pPacket->m_nOffset;

	if (false == ack.Load(&pBuf, len))
		return;

	User * pUser = NProxy::GetUser(ack.user_seq);
	if (NULL == pUser)
	{
		DEBUGLOG("%s : pUser is NULL", __FUNCTION__);
		return;
	}

	if (true == pUser->GetDisconnectStatus())
	{
		// VC처리
		if (ACK_OK == ack.result)
		{
			NLogic::NFunction::VCProcess(pUser, EM_VCINDEX_GUILD_BUFF_GACHYA);
		}

		pUser->OnDisconnect();
		return;
	}

	pUser->SetState(NState::Static::Instance().MAINFRIENDLIST());

	if (ACK_OK != ack.result)
	{
		::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();
		*pAck << static_cast<int16_t>(ack.result);
		pAck->MakePacket(CMD_SC_GUILD_BUFF_GACHYA);
		pUser->Send(pAck);
		return;
	}

	::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();
	*pAck << static_cast<int16_t>(ACK_OK);
	*pAck << static_cast<int16_t>(ack.buff_tid);
	*pAck << static_cast<uint8_t>(ack.buff_level);
	*pAck << static_cast<uint16_t>(ack.buff_value);
	pAck->MakePacket(CMD_SC_GUILD_BUFF_GACHYA);
	pUser->Send(pAck);

	NLogic::Buff * pBuff = pUser->GetBuff();
	if (NULL != pBuff)
	{
		NLogic::Buff::Data * pBuffData = pBuff->GetData(NLogic::Buff::BuffType::GUILD);
		if (NULL != pBuffData)
		{
			pBuffData->u8type			= static_cast<int>(NLogic::Buff::BuffType::GUILD);
			pBuffData->u16skill_tid		= ack.buff_tid;
			pBuffData->u8skill_level	= ack.buff_level;
			pBuffData->s16skill_value	= ack.buff_value;
			pBuffData->_regdate	= 1;
		}
	}

	// VC처리
	NLogic::NFunction::VCProcess(pUser, EM_VCINDEX_GUILD_BUFF_GACHYA);

	// 버프 정보 전송
	NLogic::NFunction::SendSkillBuff(pUser);

	// Wallet 정보 전송
	NLogic::NFunction::SendMyWallet(pUser);
}

void
GuildServer::Msg::OnUpdateGuildJoinPasswordAck(Dispatcher::Session * pSession, ::Network::Packet * pPacket)
{
	UpdateGuildJoinPasswordAck ack;
	const char * pBuf = pPacket->GetOffsetPtr();
	size_t len = pPacket->m_nEnd - pPacket->m_nOffset;

	if (false == ack.Load(&pBuf, len))
		return;

	User * pUser = NProxy::GetUser(ack.user_seq);
	if (NULL == pUser)
	{
		DEBUGLOG("%s : pUser is NULL", __FUNCTION__);
		return;
	}

	::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();
	*pAck << static_cast<int16_t>(ack.result);
	pAck->MakePacket(CMD_SC_GUILD_KEY_UPDATE);
	pUser->Send(pAck);
}

void
GuildServer::Msg::OnUpdateGuildNoticeAck(Dispatcher::Session * pSession, ::Network::Packet * pPacket)
{
	UpdateGuildNoticeAck ack;
	const char * pBuf = pPacket->GetOffsetPtr();
	size_t len = pPacket->m_nEnd - pPacket->m_nOffset;

	if (false == ack.Load(&pBuf, len))
		return;

	User * pUser = NProxy::GetUser(ack.user_seq);
	if (NULL == pUser)
	{
		DEBUGLOG("%s : pUser is NULL", __FUNCTION__);
		return;
	}

	::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();
	*pAck << static_cast<int16_t>(ack.result);
	pAck->MakePacket(CMD_SC_GUILD_LIST_VIEW_STATE_UPDATE);
	pUser->Send(pAck);
}

void
GuildServer::Msg::OnUpdateGuildNoticeTextAck(Dispatcher::Session * pSession, ::Network::Packet * pPacket)
{
	UpdateGuildNoticeTextAck ack;
	const char * pBuf = pPacket->GetOffsetPtr();
	size_t len = pPacket->m_nEnd - pPacket->m_nOffset;

	if (false == ack.Load(&pBuf, len))
		return;

	User * pUser = NProxy::GetUser(ack.user_seq);
	if (NULL == pUser)
	{
		DEBUGLOG("%s : pUser is NULL", __FUNCTION__);
		return;
	}

	::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();
	*pAck << static_cast<int16_t>(ack.result);
	pAck->MakePacket(CMD_SC_GUILD_DESCRIPTION_UPDATE);
	pUser->Send(pAck);
}

void
GuildServer::Msg::OnMyGuildInfoAck(Dispatcher::Session * pSession, ::Network::Packet * pPacket)
{

	MyGuildInfoAck ack;
	const char * pBuf = pPacket->GetOffsetPtr();
	size_t len = pPacket->m_nEnd - pPacket->m_nOffset;

	if (false == ack.Load(&pBuf, len))
		return;

	User * pUser = NProxy::GetUser(ack.user_seq);
	if (NULL == pUser)
	{
		DEBUGLOG("%s : pUser is NULL", __FUNCTION__);
		return;
	}

	// 길드에서 추방되거나, 길드 정보가 없는 경우
	if (ack.result == ACK_GUILD_MEMBER_LOGIN_WAS_KICKEDOUT
			|| ack.result == ACK_GUILD_INFO_FAILED)
	{
		::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();
		*pAck << static_cast<int16_t>(ack.result);
		pAck->MakePacket(CMD_SC_GUILD_MYINFO);
		pUser->Send(pAck);

		if (ack.result == ACK_GUILD_MEMBER_LOGIN_WAS_KICKEDOUT )
		{ // 추방 되었을 때에만 초기화를 한다.
			pUser->SetGuildSeq(0);
			pUser->SetGuildName("");
			pUser->SetGuildGrade(0);
			pUser->FlushUserInfo();
		}

		// 길드 버프 초기화
		NLogic::Buff * pBuff = pUser->GetBuff();
		if (NULL == pBuff)
			return;

		NLogic::Buff::Data * pBuffData = pBuff->GetData(NLogic::Buff::BuffType::GUILD);
		if (NULL == pBuffData)
			return;

		pBuffData->Clear();

		// 버프 정보 전송
		NLogic::NFunction::SendSkillBuff(pUser);

		// 내정보 타 유저에게 전송
		NLogic::Space * pSpace = pUser->GetSpace();
		if (NULL == pSpace)
			return;

		const NLogic::Space::USERTREE & clsUserTree = pSpace->GetUserTree();
		std::for_each(clsUserTree.begin(), clsUserTree.end(), [&](const std::pair<const int, ProjectZ::User*>& pair) {
			if (NULL != pair.second && pair.first != pUser->GetUserSeq())
			{
				NLogic::NFunction::SendCharacterInfoSimple(pUser, pair.second);
			}
		} );

		return;
	}

	::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();
	*pAck << static_cast<int16_t>(ack.result);
	*pAck << static_cast<uint32_t>(ack.stInfo.seq);
	if ( ack.stInfo.master_seq == ack.user_seq )
		*pAck << static_cast<uint8_t>(1);
	else
		*pAck << static_cast<uint8_t>(10);

	*pAck << ack.stInfo.name.c_str();
	*pAck << static_cast<uint32_t>(ack.stInfo.point);
	*pAck << static_cast<uint8_t>(ack.stInfo.level);
	*pAck << static_cast<uint8_t>(ack.stInfo.max_member_count);
	*pAck << static_cast<uint8_t>(ack.stInfo.member_count);
	*pAck << static_cast<uint32_t>(ack.stInfo.rank);

	pAck->MakePacket(CMD_SC_GUILD_MYINFO);
	pUser->Send(pAck);

	// 길드 정보 설정
	pUser->SetGuildGrade(ack.stInfo.level);
	pUser->SetGuildName(ack.stInfo.name.c_str());

	// 길드 버프 설정
	NLogic::Buff * pBuff = pUser->GetBuff();
	if (NULL == pBuff)
		return;

	NLogic::Buff::Data * pBuffData = pBuff->GetData(NLogic::Buff::BuffType::GUILD);
	if (NULL == pBuffData)
		return;

	pBuffData->Clear();

	if (0 < ack.stInfo.buff_type)
	{
		pBuffData->u8type			= static_cast<uint8_t>(NLogic::Buff::BuffType::GUILD);
		pBuffData->u16skill_tid		= ack.stInfo.buff_type;
		pBuffData->u8skill_level	= ack.stInfo.buff_level;
		pBuffData->s16skill_value	= ack.stInfo.buff_value;
		pBuffData->_regdate	= 1;

		// 버프 정보 전송
		NLogic::NFunction::SendSkillBuff(pUser);
	}
}


void
GuildServer::Msg::OnRecoverGuildAck(Dispatcher::Session * pSession, ::Network::Packet * pPacket)
{

	RecoverGuildAck ack;
	const char * pBuf = pPacket->GetOffsetPtr();
	size_t len = pPacket->m_nEnd - pPacket->m_nOffset;

	if (false == ack.Load(&pBuf, len))
		return;

	User * pUser = NProxy::GetUser(ack.user_seq);
	if (NULL == pUser)
	{
		DEBUGLOG("%s : pUser is NULL", __FUNCTION__);
		return;
	}

	if ( ACK_OK == ack.result )
	{
		pUser->SetGuildSeq( ack.stInfo.seq );
		pUser->SetGuildGrade(ack.stInfo.level);
		pUser->SetGuildName(ack.stInfo.name.c_str());
		pUser->FlushUserInfo();
	}

	::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();
	*pAck << static_cast<int16_t>(ack.result);
	*pAck << static_cast<uint32_t>(ack.stInfo.seq);
	if ( ack.stInfo.master_seq == ack.user_seq )
		*pAck << static_cast<uint8_t>(1);
	else
		*pAck << static_cast<uint8_t>(10);

	*pAck << ack.stInfo.name.c_str();
	*pAck << static_cast<uint32_t>(ack.stInfo.point);
	*pAck << static_cast<uint8_t>(ack.stInfo.level);
	*pAck << static_cast<uint8_t>(ack.stInfo.max_member_count);
	*pAck << static_cast<uint8_t>(ack.stInfo.member_count);
	*pAck << static_cast<uint32_t>(ack.stInfo.rank);

	pAck->MakePacket(CMD_SC_GUILD_MYINFO);
	pUser->Send(pAck);



	// 길드 버프 설정
	NLogic::Buff * pBuff = pUser->GetBuff();
	if (NULL == pBuff)
		return;

	NLogic::Buff::Data * pBuffData = pBuff->GetData(NLogic::Buff::BuffType::GUILD);
	if (NULL == pBuffData)
		return;

	pBuffData->Clear();

	if (0 < ack.stInfo.buff_type)
	{
		pBuffData->u8type			= static_cast<uint8_t>(NLogic::Buff::BuffType::GUILD);
		pBuffData->u16skill_tid		= ack.stInfo.buff_type;
		pBuffData->u8skill_level	= ack.stInfo.buff_level;
		pBuffData->s16skill_value	= ack.stInfo.buff_value;
		pBuffData->_regdate	= 1;

		// 버프 정보 전송
		NLogic::NFunction::SendSkillBuff(pUser);
	}
}


void
GuildServer::Msg::OnGuildInfoAck(Dispatcher::Session * pSession, ::Network::Packet * pPacket)
{
	GuildInfoAck ack;
	const char * pBuf = pPacket->GetOffsetPtr();
	size_t len = pPacket->m_nEnd - pPacket->m_nOffset;

	if (false == ack.Load(&pBuf, len))
		return;

	User * pUser = NProxy::GetUser(ack.user_seq);
	if (NULL == pUser)
	{
		DEBUGLOG("%s : pUser is NULL", __FUNCTION__);
		return;
	}

	::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();
	*pAck << static_cast<int16_t>(ack.result);
	*pAck << static_cast<uint32_t>(ack.stInfo.seq);
	*pAck << ack.stInfo.name.c_str();
	*pAck << std::to_string(ack.stInfo.master_socialid).c_str();
	*pAck << ack.stInfo.master_nickname.c_str();
	*pAck << ack.stInfo.master_profile_url.c_str();
	*pAck << static_cast<uint32_t>(ack.stInfo.point);
	*pAck << static_cast<uint32_t>(ack.stInfo.max_point);
	*pAck << static_cast<uint8_t>(ack.stInfo.level);
	*pAck << static_cast<uint8_t>(ack.stInfo.max_member_count);
	*pAck << static_cast<uint8_t>(ack.stInfo.member_count);
	*pAck << static_cast<uint16_t>(ack.stInfo.buff_type);
	*pAck << static_cast<uint8_t>(ack.stInfo.buff_level);
	*pAck << static_cast<uint16_t>(ack.stInfo.buff_value);
	*pAck << static_cast<uint8_t>(ack.stInfo.notice_flag);
	*pAck << ack.stInfo.password.c_str();
	*pAck << ack.stInfo.notice_text.c_str();
	*pAck << static_cast<uint32_t>(ack.stInfo.rank); // TODO redis에서 실시간으로 랭킹을 알아와야 한다.
	*pAck << static_cast<uint16_t>(ack.stInfo.master_level);



//	DEBUGLOG("%s> result: %d, guild_seq: %d, name: %s, master' socialid: %s, nickname: %s, profile: %s, password: %s, notice: %s"
//			, __FUNCTION__
//			, ack.result, ack.stInfo.seq, ack.stInfo.name.c_str(), std::to_string(ack.stInfo.master_socialid).c_str(), ack.stInfo.master_nickname.c_str(), ack.stInfo.master_profile_url.c_str()
//			, ack.stInfo.password.c_str(), ack.stInfo.notice_text.c_str()
//			);


	pAck->MakePacket(CMD_SC_GUILD_MENU_INFO);
	pUser->Send(pAck);
}


void
GuildServer::Msg::OnGuildMemberAck(Dispatcher::Session * pSession, ::Network::Packet * pPacket)
{
	GuildMemberAck ack;
	const char * pBuf = pPacket->GetOffsetPtr();
	size_t len = pPacket->m_nEnd - pPacket->m_nOffset;

	if (false == ack.Load(&pBuf, len))
		return;

	User * pUser = NProxy::GetUser(ack.user_seq);
	if (NULL == pUser)
	{
		DEBUGLOG("%s : pUser is NULL", __FUNCTION__);
		return;
	}

	::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();
	*pAck << static_cast<int16_t>(ack.result);
	*pAck << static_cast<uint8_t>(ack.array_members.size());

	//DEBUGLOG("%s> result: %d, count: %d", __FUNCTION__, ack.result, ack.array_members.size());

	auto iter = ack.array_members.begin();
	for ( ; iter != ack.array_members.end(); ++iter )
	{
		*pAck << static_cast<uint32_t>(iter->seq);
		*pAck << static_cast<uint8_t>(iter->guild_grade);
		*pAck << static_cast<uint8_t>(0); // 휴면 기간
		*pAck << static_cast<uint8_t>(1); // 접속 요청 여부 (0 : 접속요청 할수 있는 상태, 1 : 접속요청할 수 없는 상태(이미 오늘 접속요청을 보냄)) ==> 접속 요청시에  친구리스트에 사용한 로직과 같으나, 친구관계가 아닌 사람에게 보낼때 우정포인트 획득은 없습니다.
		*pAck << static_cast<uint16_t>(iter->server_id);
		*pAck << static_cast<uint32_t>(iter->point);
		*pAck << static_cast<uint32_t>(iter->level);
		*pAck << std::to_string(iter->socialid).c_str();
		*pAck << iter->nickname.c_str();
		*pAck << iter->profile_url.c_str();

		//DEBUGLOG("%s> Member info> user_seq: %d, grade: %d, server: %d, level: %d", __FUNCTION__, iter->seq, iter->guild_grade, iter->server_id, iter->level);
	}


	pAck->MakePacket(CMD_SC_GUILD_MEMBER_LIST);
	pUser->Send(pAck);
}


void
GuildServer::Msg::OnCreateGuildAck(Dispatcher::Session * pSession, ::Network::Packet * pPacket)
{
	CreateGuildAck ack;
	const char * pBuf = pPacket->GetOffsetPtr();
	size_t len = pPacket->m_nEnd - pPacket->m_nOffset;

	if (false == ack.Load(&pBuf, len))
		return;

	User * pUser = NProxy::GetUser(ack.user_seq);
	if (NULL == pUser)
	{
		DEBUGLOG("%s : pUser is NULL", __FUNCTION__);
		return;
	}

	//DEBUGLOG("%s> result: %d", __FUNCTION__, ack.result );

	if ( ACK_OK == ack.result )
	{
		// 길드 생성 비용 차감
		if ( 0 < ack.guild_create_gold )
			NLogic::NFunction::ModifyGold(pUser, ack.guild_create_gold * -1);

		pUser->SetGuildSeq( ack.guild_seq );
		pUser->SetGuildGrade(ack.guild_grade);
		pUser->SetGuildName(ack.guild_name.c_str());
		pUser->FlushUserInfo();
		DEBUGLOG("%s> user_seq: %d, guild_seq: %d", __FUNCTION__, pUser->GetUserSeq(), pUser->GetGuildSeq() );
	}

	if (true == pUser->GetDisconnectStatus())
	{
		pUser->OnDisconnect();
		return;
	}

	pUser->SetState(NState::Static::Instance().MAINFRIENDLIST());

	::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();
	*pAck << static_cast<int16_t>(ack.result);
	*pAck << static_cast<uint32_t>(ack.guild_seq);
	pAck->MakePacket(CMD_SC_GUILD_CREATE);
	pUser->Send(pAck);

	// 내정보 타 유저에게 전송
	NLogic::Space * pSpace = pUser->GetSpace();
	if (NULL == pSpace)
		return;

	const NLogic::Space::USERTREE & clsUserTree = pSpace->GetUserTree();
	std::for_each(clsUserTree.begin(), clsUserTree.end(), [&](const std::pair<const int, ProjectZ::User*>& pair) {
		if (NULL != pair.second && pair.first != pUser->GetUserSeq())
		{
			NLogic::NFunction::SendCharacterInfoSimple(pUser, pair.second);
		}
	} );
}

void
GuildServer::Msg::OnJoinGuildAck(Dispatcher::Session * pSession, ::Network::Packet * pPacket)
{
	JoinGuildAck ack;
	const char * pBuf = pPacket->GetOffsetPtr();
	size_t len = pPacket->m_nEnd - pPacket->m_nOffset;

	if (false == ack.Load(&pBuf, len))
		return;

	User * pUser = NProxy::GetUser(ack.user_seq);
	if (NULL == pUser)
	{
		DEBUGLOG("%s : pUser is NULL", __FUNCTION__);
		return;
	}

	DEBUGLOG("%s> result: %d", __FUNCTION__, ack.result );

	if ( ACK_OK == ack.result )
	{
		pUser->SetGuildSeq( ack.guild_seq );
		pUser->SetGuildGrade(ack.guild_grade);
		pUser->SetGuildName(ack.guild_name.c_str());
		pUser->FlushUserInfo();

		NLogic::Buff * pBuff = pUser->GetBuff();
		if (NULL != pBuff)
		{
			NLogic::Buff::Data * pBuffData = pBuff->GetData(NLogic::Buff::BuffType::GUILD);
			if (NULL != pBuffData)
			{
				pBuffData->Clear();

				if (0 < ack.buff_tid)
				{
					pBuffData->u8type			= static_cast<int>(NLogic::Buff::BuffType::GUILD);
					pBuffData->u16skill_tid		= ack.buff_tid;
					pBuffData->u8skill_level	= ack.buff_level;
					pBuffData->s16skill_value	= ack.buff_value;
					pBuffData->_regdate	= 1;
				}
			}
		}

		DEBUGLOG("%s> user_seq: %d, guild_seq: %d", __FUNCTION__, pUser->GetUserSeq(), pUser->GetGuildSeq() );
	}



	if (true == pUser->GetDisconnectStatus())
	{
		pUser->OnDisconnect();
		return;
	}

	pUser->SetState(NState::Static::Instance().MAINFRIENDLIST());

	::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();
	*pAck << static_cast<int16_t>(ack.result);
	*pAck << static_cast<int32_t>(ack.guild_seq);

	pAck->MakePacket(CMD_SC_GUILD_APPLY_ADMISSION);
	pUser->Send(pAck);

	// 내정보 타 유저에게 전송
	NLogic::Space * pSpace = pUser->GetSpace();
	if (NULL == pSpace)
		return;

	const NLogic::Space::USERTREE & clsUserTree = pSpace->GetUserTree();
	std::for_each(clsUserTree.begin(), clsUserTree.end(), [&](const std::pair<const int, ProjectZ::User*>& pair) {
		if (NULL != pair.second && pair.first != pUser->GetUserSeq())
		{
			NLogic::NFunction::SendCharacterInfoSimple(pUser, pair.second);
		}
	} );
}


void
GuildServer::Msg::OnSearchGuildAck(Dispatcher::Session * pSession, ::Network::Packet * pPacket)
{
	SearchGuildAck ack;
	const char * pBuf = pPacket->GetOffsetPtr();
	size_t len = pPacket->m_nEnd - pPacket->m_nOffset;

	if (false == ack.Load(&pBuf, len))
		return;

	User * pUser = NProxy::GetUser(ack.user_seq);
	if (NULL == pUser)
	{
		DEBUGLOG("%s : pUser is NULL", __FUNCTION__);
		return;
	}

	::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();
	*pAck << static_cast<int16_t>(ack.result);
	if ( ACK_OK == ack.result )
	{
		*pAck << static_cast<int8_t>(ack.array_Guilds.size()); // 0 or 1 only

		auto iter = ack.array_Guilds.begin();
		for ( ; iter != ack.array_Guilds.end(); ++iter )
		{
			*pAck << static_cast<uint32_t>(iter->seq);
			*pAck << iter->name.c_str();
			*pAck << iter->master_nickname.c_str();
			*pAck << static_cast<uint16_t>(iter->master_level);
			*pAck << static_cast<uint8_t>(iter->notice_flag);
			*pAck << static_cast<uint32_t>(iter->point);
			*pAck << static_cast<uint32_t>(iter->prev_point);
			*pAck << static_cast<uint8_t>(iter->level);
			*pAck << static_cast<uint8_t>(iter->max_member_count);
			*pAck << static_cast<uint8_t>(iter->member_count);
			*pAck << iter->notice_text.c_str();

			//DEBUGLOG("%s> info> seq: %d, name: %s, grade: %d, master: %s", __FUNCTION__, iter->seq, iter->name.c_str(), iter->level, iter->master_nickname.c_str());
		}
	}

	pAck->MakePacket(CMD_SC_GUILD_FIND);
	pUser->Send(pAck);
}


void
GuildServer::Msg::OnUpdateGuildLevelAck(Dispatcher::Session * pSession, ::Network::Packet * pPacket)
{
	UpdateGuildLevelAck ack;
	const char * pBuf = pPacket->GetOffsetPtr();
	size_t len = pPacket->m_nEnd - pPacket->m_nOffset;

	if (false == ack.Load(&pBuf, len))
		return;

	User * pUser = NProxy::GetUser(ack.user_seq);
	if (NULL == pUser)
	{
		DEBUGLOG("%s : pUser is NULL", __FUNCTION__);
		return;
	}

	::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();
	*pAck << static_cast<int16_t>(ack.result);
	if ( ACK_OK == ack.result )
	{
		*pAck << static_cast<uint8_t>(ack.level);
		*pAck << static_cast<uint32_t>(ack.point);
		*pAck << static_cast<uint32_t>(ack.next_level_point);
	}

	pAck->MakePacket(CMD_SC_GUILD_GRADE_UP);
	pUser->Send(pAck);
}


void
GuildServer::Msg::OnGuildListAck(Dispatcher::Session * pSession, ::Network::Packet * pPacket)
{
	GuildListAck ack;
	const char * pBuf = pPacket->GetOffsetPtr();
	size_t len = pPacket->m_nEnd - pPacket->m_nOffset;

	if (false == ack.Load(&pBuf, len))
		return;

	User * pUser = NProxy::GetUser(ack.user_seq);
	if (NULL == pUser)
	{
		DEBUGLOG("%s : pUser is NULL", __FUNCTION__);
		return;
	}

	::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();
	*pAck << static_cast<int16_t>(ack.result);

	if ( ACK_OK == ack.result )
	{
		*pAck << static_cast<int8_t>(ack.array_Guilds.size()); // 0 or 1 only

		auto iter = ack.array_Guilds.begin();
		for ( ; iter != ack.array_Guilds.end(); ++iter )
		{
			*pAck << static_cast<uint32_t>(iter->seq);
			*pAck << iter->name.c_str();
			*pAck << iter->master_nickname.c_str();
			*pAck << static_cast<uint16_t>(iter->master_level);
			*pAck << static_cast<uint8_t>(iter->notice_flag);
			*pAck << static_cast<uint32_t>(iter->point);
			*pAck << static_cast<uint32_t>(iter->prev_point);
			*pAck << static_cast<uint8_t>(iter->level);
			*pAck << static_cast<uint8_t>(iter->max_member_count);
			*pAck << static_cast<uint8_t>(iter->member_count);
			*pAck << iter->notice_text.c_str();
			*pAck << static_cast<uint32_t>(iter->rank);
			*pAck << static_cast<uint32_t>(iter->prev_rank);

			//DEBUGLOG("%s> info> seq: %d, name: %s, grade: %d, master: %s", __FUNCTION__, iter->seq, iter->name.c_str(), iter->level, iter->master_nickname.c_str());
		}
	}

	pAck->MakePacket(CMD_SC_GUIlD_LIST);
	pUser->Send(pAck);
}


void
GuildServer::Msg::OnSendGuildMailCheckAck(Dispatcher::Session * pSession, ::Network::Packet * pPacket)
{
	SendGuildMailCheckAck ack;
	const char * pBuf = pPacket->GetOffsetPtr();
	size_t len = pPacket->m_nEnd - pPacket->m_nOffset;

	if (false == ack.Load(&pBuf, len))
		return;

	User * pUser = NProxy::GetUser(ack.user_seq);
	if (NULL == pUser)
	{
		DEBUGLOG("%s : pUser is NULL", __FUNCTION__);
		return;
	}

	if (ACK_OK != ack.result)
	{
		::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();
		*pAck << static_cast<int16_t>(ack.result);
		pAck->MakePacket(CMD_SC_GUILD_WRITE_MAIL);
		pUser->Send(pAck);
		return;
	}

	NLogic::Bag * pBag = NULL;
	NLogic::Item * pItem = NULL;

	if (0 < ack.item_seq)
	{
		pBag = pUser->GetBag(static_cast<INVEN_BAG_TYPE>(ack.bag_type));
		if (NULL == pBag)
		{
			::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();
			*pAck << static_cast<int16_t>(ACK_UNKNOWN_ERROR);
			pAck->MakePacket(CMD_SC_GUILD_WRITE_MAIL);
			pUser->Send(pAck);
			return;
		}

		pItem = pBag->GetItem(ack.item_seq);
		if (NULL == pItem)
		{
			::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();
			*pAck << static_cast<int16_t>(ACK_UNKNOWN_ERROR);
			pAck->MakePacket(CMD_SC_GUILD_WRITE_MAIL);
			pUser->Send(pAck);
			return;
		}
	}

	NLogic::MailBox::Mail::Data clsData;

	clsData.send_user_seq		= pUser->GetUserSeq();
	clsData.send_user_nickname	= pUser->GetUserInfo().nickname.c_str();
	clsData.send_user_imageurl	= pUser->GetUserInfo().profile_url.c_str();
	clsData.recv_user_seq		= ack.recv_user_seq;
	clsData.message				= ack.msg.c_str();

	if (NULL != pItem)
	{
		clsData.gift_status	|= EM_GIFT_ITEM;
		clsData.item		= pItem->GetData();
	}

	if (0 < ack.gold)
	{
		clsData.gift_status	|= EM_GIFT_GOLD;
		clsData.gold		= ack.gold;
	}

	if (false == NLogic::NFunction::SendMail(pUser, clsData))
	{
		DEBUGLOG("%s : false == NLogic::NFunction::SendMail", __FUNCTION__);
		::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();
		*pAck << static_cast<int16_t>(ACK_DB_ERROR);
		pAck->MakePacket(CMD_SC_GUILD_WRITE_MAIL);
		pUser->Send(pAck);
		return;
	}

	if (NULL != pItem)
	{
		pBag->PopItem(ack.item_seq);
		pItem->DeleteDatabaseItemInfo(NLogic::Item::ItemStatus::EM_ITEM_STATUS_SEND_MAIL);
	}

	int total_gold = ack.tax + ack.gold;
	NLogic::NFunction::ModifyGold(pUser, total_gold * -1);

	::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();
	*pAck << static_cast<int16_t>(ACK_OK);
	pAck->MakePacket(CMD_SC_GUILD_WRITE_MAIL);
	pUser->Send(pAck);
}

void
GuildServer::Msg::OnGuildCoolDownAck(Dispatcher::Session * pSession, ::Network::Packet * pPacket)
{
	GuildCoolDownAck ack;
	const char * pBuf = pPacket->GetOffsetPtr();
	size_t len = pPacket->m_nEnd - pPacket->m_nOffset;

	if (false == ack.Load(&pBuf, len))
		return;

	User * pUser = NProxy::GetUser(ack.user_seq);
	if (NULL == pUser)
	{
		DEBUGLOG("%s : pUser is NULL", __FUNCTION__);
		return;
	}

	::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();
	*pAck << static_cast<int16_t>(ack.result);
	*pAck << static_cast<uint64_t>(time(NULL));
	*pAck << static_cast<uint64_t>(ack.leave_time);

	//DEBUGLOG("%s> time: %u, leave_time: %u", __FUNCTION__, time(NULL), ack.leave_time );

	pAck->MakePacket(CMD_SC_GUILD_COOLDOWN);
	pUser->Send(pAck);
}

void
GuildServer::Msg::OnChatAck(Dispatcher::Session* pSession, ::Network::Packet * pPacket )
{
	::BroadcastGuildChatAck ans;

	const char* pBuf = pPacket->GetOffsetPtr();
	size_t len = pPacket->m_nEnd - pPacket->m_nOffset;

	if(false == ans.Load(&pBuf, len))
	{
		return;
	}

	//DEBUGLOG("%s> sender: %s, chat: %s", __FUNCTION__, ans.nickname.c_str(), ans.chat.c_str() );

	auto iter = ans.array_Members.begin();
	for ( ; iter != ans.array_Members.end(); ++iter )
	{
		uint32_t receiver_seq = *iter;

		User * pTargetUser = GetUser(receiver_seq);
		if (NULL == pTargetUser)
			continue;


		::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();
		*pAck << static_cast<int16_t>(ACK_OK);
		*pAck << static_cast<uint8_t>(::ProjectZ::NCommand::NWorld::CHATTYPE_GUILD);
		*pAck << ans.nickname.c_str();
		*pAck << static_cast<uint16_t>(0); // 받는 유저명
		*pAck << ans.chat.c_str();
		*pAck << ans.user_seq;
		*pAck << receiver_seq;

		pAck->MakePacket(CMD_SN_CHAT_MESSAGE);
		pTargetUser->Send(pAck);

		//DEBUGLOG("\treceiver: %d", receiver_seq );

	}
}



} /* namespace NProxy */ } /* namespace ProjectZ */
